1 module project.gen;
2 import std.path:buildNormalizedPath;
3 import std.file;
4 import std.format:format;
5 import std.process;
6 import std.array:join,split,array;
7 
8 struct TemplateInfo
9 {
10 	string initMethod=q{
11 		setFont(HipDefaultAssets.getDefaultFontWithSize(62));
12 	},
13 	update="",
14 	render=q{
15 		drawText("You can start using the D Scripting API Here!", 400, 300, HipColor.white, 
16 			HipTextAlign.CENTER,  HipTextAlign.CENTER
17 		);
18 	},
19 	dispose="";
20 }
21 
22 struct DubProjectInfo
23 {
24 	string author = "HipremeEngine";
25 	string projectName = "Hipreme Engine Test";
26 	string desc = "Hipreme Engine test scene";
27 }
28 
29 string generateCodeTemplate(TemplateInfo info = TemplateInfo())
30 {
31 	return format!q{
32 module gamescript.entry;
33 import hip.api;
34 
35 /**
36 *	Call `dub` to generate the DLL, after that, just execute `dub -c run` for starting your project
37 */
38 class MainScene : AScene, IHipPreloadable
39 {
40 	mixin Preload;
41 	
42 	/** Constructor */
43 	override void initialize()
44 	{
45 		%s
46 	}
47 	/** Called every frame */
48 	override void update(float dt)
49 	{
50 		%s
51 	}
52 	/** Renderer only, may not be called every frame */
53 	override void render()
54 	{
55 		%s
56 	}
57 	/** Pre destroy */
58 	override void dispose()
59 	{
60 		%s
61 	}
62 	void onResize(uint width, uint height){}
63 }
64 
65 mixin HipEngineMain!MainScene;
66 	}(info.initMethod, info.update, info.render, info.dispose);
67 }
68 
69 
70 string escapeWindowsPathSep(string input)
71 {
72 	string output = "";
73 	foreach(ch; input)
74 		if(ch == '\\')
75 			output~="\\\\";
76 		else
77 			output~= ch;
78 	return output;
79 }
80 
81 string generateDubProject(DubProjectInfo info)
82 {
83 	import std.conv;
84 	import std.uni:toLower;
85 	import std.algorithm:map;
86 	dstring outputName = info.projectName.split(" ").join("_").array;
87 	dstring name = outputName.map!(character => character.toLower).array;
88 
89 	return format!`{
90 	"$schema": "https://raw.githubusercontent.com/Pure-D/code-d/master/json-validation/dub.schema.json",
91 	"authors": ["%s"],
92 	"description" : "%s",
93 	"license": "proprietary",
94 	"targetName" : "%s",
95 	"name" : "%s",
96 	"engineModules": [
97 		"util",
98 		"timer",
99 		"tween",
100 		"math"
101 	],
102 	"stringImportPaths": [
103 		"#PROJECT"
104 	],
105 	"dflags-ldc": ["--disable-verify", "--oq"],
106 	"preBuildCommands-posix": [
107 		"export DFLAGS= && rdmd #HIPREME_ENGINE/tools/build/getmodules.d #PROJECT/source/ #PROJECT/scriptmodules.txt"
108 	],
109 	"preBuildCommands-windows": [
110 		"set DFLAGS= && rdmd #HIPREME_ENGINE/tools/build/getmodules.d #PROJECT/source/ #PROJECT/scriptmodules.txt"
111 	],
112 	"configurations": 
113 	[
114 		{
115 			"name" : "script",
116 			"targetType": "dynamicLibrary",
117 			"dflags-ldc": ["-link-defaultlib-shared=true"],
118 			"linkedDependencies": {"hipengine_api": {"path": "#HIPREME_ENGINE/api"}},
119 			"lflags-windows": ["/WX"],
120 			"versions": ["ScriptAPI"]
121 		},
122 		{
123 			"name": "release", 
124 			"targetType": "staticLibrary", 
125 			"dependencies": {"hipengine_api:direct": {"path": "#HIPREME_ENGINE/api"}}
126 		},
127 		{
128 			"name": "run",
129 			"targetType": "dynamicLibrary",
130 			"lflags-windows": [
131 				"/WX"
132 			],
133 			"postGenerateCommands-windows": ["cd /d #HIPREME_ENGINE && dub -c script -- $PACKAGE_DIR"],
134 			"postGenerateCommands-linux": ["cd #HIPREME_ENGINE && dub -c script -- $PACKAGE_DIR"]
135 		}
136 	],
137 	"versions" : [
138 		"HipMathAPI",
139 		"HipremeAudio"
140 	]
141 }
142 `(info.author, info.desc, outputName, name);
143 }
144 
145 string generateReadmeContent(string projectName)
146 {
147 	return "# "~projectName~"\n"~projectName~" is made using Hipreme Engine.\n" ~
148 		"## Building Instructions \n" ~
149 		"1. Run `dub hipreme_engine:build_selector`\n" ~
150 		"2. Select 'Select Game'\n" ~
151 		"3. Select the folder containing "~projectName~"\n"~
152 		"4. Now you can simply choose the platform to build for";
153 }
154 
155 string generateVSCodeDebuggerLaunch(string enginePath)
156 {
157 	import std.system;
158 	string hipEnginePath = enginePath;
159 	string hipEngineExecutable = (buildNormalizedPath(hipEnginePath, "bin", "desktop", "hipreme_engine") ~ ((os == OS.linux) ? "" : ".exe")).escapeWindowsPathSep;
160 	return format!q{
161 {
162     // Use IntelliSense to learn about possible attributes.
163     // Hover to view descriptions of existing attributes.
164     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
165 	// Auto Generated by HipremeEngine project generator.
166 	// Automatically handle SIGUSR1 and SIGUSR2 as they are currently used in semaphore.wait
167     "version": "0.2.0",
168     "configurations": [
169         {
170             "name": "Debug",
171             "type": "gdb",
172             "request": "launch",
173             "target": "%s",
174             "cwd": "${workspaceRoot}",
175             "arguments": "${workspaceRoot}",
176             "debugger_args": [
177                 "-ex", "handle SIGUSR1 noprint",
178                 "-ex", "handle SIGUSR2 noprint"
179             ]
180         }
181     ]
182 }
183 }(hipEngineExecutable);
184 }
185 
186 import commons;
187 bool generateProject(ref Terminal t, string projectPath, string enginePath,
188 DubProjectInfo dubInfo, TemplateInfo templateInfo)
189 {
190 	string dubProj = generateDubProject(dubInfo);
191 	string codeTemplate = generateCodeTemplate(templateInfo);
192 	string debugLauncher = generateVSCodeDebuggerLaunch(enginePath);
193 
194 	try
195 	{
196 	    //Project folder
197 		t.writeln("Creating project folder");
198 		mkdirRecurse(projectPath);
199 		//Source Folder
200 		t.writeln("Creating scripts folder");
201 		mkdirRecurse(buildNormalizedPath(projectPath, "source", "gamescript"));
202 		//Assets Folder
203 		t.writeln("Creating assets folder");
204 		mkdirRecurse(buildNormalizedPath(projectPath, "assets"));
205 		//VSCode Folder
206 		t.writeln("Creating vscode folder");
207 		mkdirRecurse(buildNormalizedPath(projectPath, ".vscode"));
208 
209 		t.writeln("Writing code template for gamescript/entry.d");
210 		std.file.write(buildNormalizedPath(projectPath, "source", "gamescript", "entry.d"), codeTemplate);
211 		t.writeln("Writing dub.template.json");
212 		std.file.write(buildNormalizedPath(projectPath, "dub.template.json"), dubProj);
213 		t.writeln("Writing README.md");
214 		std.file.write(buildNormalizedPath(projectPath, "README.md"), generateReadmeContent(dubInfo.projectName));
215 		t.writeln("Writing VSCode debug launcher");
216 		std.file.write(buildNormalizedPath(projectPath, ".vscode", "launch.json"), debugLauncher);
217 
218 		t.writeln("Writing .gitignore");
219 		std.file.write(buildNormalizedPath(projectPath, ".gitignore"),  q{
220 dub.selections.json
221 .DS_Store
222 .dub
223 .history
224 .vs
225 bin
226 *.exe
227 *.dll
228 *.dll_hiptempdll
229 *.so
230 *.lib
231 *.a
232 *.pdb
233 });
234 	}
235 	catch(Exception e)
236 	{
237 		t.writelnError(e.toString);
238 		return false;
239 	}
240 	return true;
241 }